package String;

/**
 * String 字符串
 * 字符串是不变对象，即：字符串一旦创建内容不可改变，改变一定创建新对象
 * 这是由于JAVA对字符串的优化导致的
 * 字符串的一个优化为：常量池
 * 常量池是在堆内存中开辟的一段空间，用于缓存所有使用字面量形式创建的字符串，当我们
 * 使用已有的字面量再次创建字符串时会重用对象来避免内存中堆积大量内容相同的字符串
 *
 */
public class StringDemo {
    public static void main(String[] args) {
        String s1 = "123abc";
        String s2 = "123abc";
        System.out.println("s1:"+s1);
        System.out.println("s2:"+s2);
        System.out.println(s1==s2);

        String s3 = "123abc";
        System.out.println("s3:"+s3);
        System.out.println(s2==s3);
        /*
        new是强制操作，一定创建新对象
        面试题经常问：下面代码创建了几个字符串对象
        String s = new String("123abc");
        答：两个，第一个是参数“123abc”这个字面量产生的字符串对象
            第二个是new String（）产生的字符串对象
         */
        String s4 = new String("123abc");
        System.out.println("s4"+s4);
        System.out.println(s2==s4);

        s1 = s1+"!";//字符串时不变对象 修改内容会创建新对象
        System.out.println("s1"+s1);
        System.out.println("s2"+s2);
        System.out.println(s1==s2);//s1与s2的地址不同了
        /*
        字符串判断相等绝大多数的情况都是判断字符串的内容是否相同
        因此实际开发中我们都是使用字符串提供的方法equals来判断两个字符串对象的内容是否相同
         */
        //s2和s4虽然不是同一个对象，但是字符串的内容都是“123abc”，因此equals为TRUE
        boolean equal = s2.equals(s4);
        System.out.println(equal);
        /*
        编译器有一个特性：如果在编译期间可以确定一个计算表达式结果的时候编译器就会进行计算并将结果放在编译后的class文件中，这样以来JVM每次执行时就无需计算了
        下面的代码会被编译器计算并改为：
        String s5 = "123abc；//JVM运行时就会重用常量池对象
         */
        String s5 = "123"+"abc";
        System.out.println("s5:"+s5);
        System.out.println(s2==s5);

        String s = "123";
        String s6 = s+"abc";
        System.out.println("s6:"+s6);
        System.out.println(s2==s6);

        String s7 = 1+23 +"abc";
    }

    /**
     * String的优化导致字符串不适合频繁修改(开销大，性能低)
     * JAVA提供了一个专门用于修改字符串内容的API：StringBuilder
     * 其内部维护一个可变的char数组，修改性能好，开销小，并且由于是专门修改字符串的API
     * 对此提供了一套修改字符串的方法：增，删，改，插等操作
     */
    public static class StringBuilderDemo {
        public static void main(String[] args) {
            String line = "好好学习java";
            /*
            StringBuilder常见的构造方法：
            StringBulider()无参构造器创建的StringBuilder内部表示空字符串

            StringBuilder(String str)将给定字符串内容复制一份到StringBuilder
             */
     //       StringBuilder builder = new StringBuilder();
            StringBuffer builder = new StringBuffer(line);
            /*
            好好学习java
            好好学习java，为了找个好工作！
            append：追加内容
             */
            builder.append(",为了找个好工作!");
            System.out.println(builder);

            /*
            好好学习java，为了找个好工作 ！
            好好学习java，就是为了改变世界！
            replace():替换字符串部分内容
             */
            builder.replace(9,16,"就是为了让机器统治世界!");
            System.out.println(builder);

            /*
            好好学习java，就是为了改变世界!
            ,就是为了改变世界
            delete：删除当前字符串中的部分内容
             */
            builder.delete(0,8);
            System.out.println(builder);

            /*
            ,就是为了改变世界
            活着，就是为了改变世界
            insert:将给定的字符插入到指定位置
             */
            builder.insert(0,"活着");
            System.out.println(builder);

            builder.reverse();
            System.out.println(builder);
            //StringBuilder支持String的相关方法
            int len = builder.length();
            System.out.println(len);
            //可以调用toString方法将StringBuilder内部表示的内容转换为String返回
            String str = builder.toString();
            System.out.println(str);

        }
    }
}
